package com.ctshk.app.order.season.config;

import com.ctshk.common.constant.RedisConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;

import java.nio.charset.Charset;
import java.time.Duration;

/**
 * @author 谢诗宏
 * @description redis配置
 * @date 2020/12/16
 */
@Configuration
@EnableCaching
public class RedisConfig {

    /**
     * 实例化 RedisTemplate 对象
     *
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> functionDomainRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        // 设置数据存入 redis 的序列化方式
        redisTemplate.setKeySerializer(keySerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setValueSerializer(new RedisValueSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 不开启事务，用到事务都在lua脚本自己写
        redisTemplate.setEnableTransactionSupport(false);
        return redisTemplate;
    }

    @Primary
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 缓存配置对象
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        //设置缓存的默认超时时间：30分钟
        redisCacheConfiguration = redisCacheConfiguration.entryTtl(Duration.ofMinutes(30))
                // 如果是空值，不缓存
                .disableCachingNullValues()
                // 设置key序列化器
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                // 设置value序列化器
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer((valueSerializer())));
        return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)).cacheDefaults(redisCacheConfiguration).build();
    }

    private RedisSerializer<String> keySerializer() {
        //自定义key序列号，加上统一前缀，统一管理key
        return new RedisSerializer<String>() {
            private final Charset charset = Charset.forName("UTF-8");

            @Override
            public byte[] serialize(String key) throws SerializationException {
                if (StringUtils.isBlank(key)) throw new SerializationException("empty key");
                String keyPrefix = RedisConstants.KEY_PREFIX;
                String key2 = keyPrefix + key;
                return key2.getBytes(charset);
            }

            @Override
            public String deserialize(byte[] bytes) throws SerializationException {
                String keyPrefix = RedisConstants.KEY_PREFIX;
                String key = new String(bytes, charset);
                int idx = key.indexOf(keyPrefix);
                if (idx == -1) {
                    throw new SerializationException("found key without prefix");
                } else {
                    key = key.substring(idx + keyPrefix.length());
                }
                return key;
            }
        };
    }

    private RedisSerializer<Object> valueSerializer() {
        return new JdkSerializationRedisSerializer();
    }

}
